﻿using System;
using AzukiMap.Map;
using AzukiMap.MapSource;
using Geotools.Geometries;

namespace AzukiMap.Layer
{
    public class KaMapLayer : TiledLayer
    {
        KaMapSource _kaMapSource;

        public KaMapSource DataSource
        {
            get { return _kaMapSource; }
        }

        public KaMapLayer(KaMapSource mapSource, MapCanvas mapCanvas, string name)
            : base(mapSource, mapCanvas, name)
        {
            _kaMapSource = mapSource;
        }

        public KaMapLayer(KaMapSource mapSource, MapCanvas mapCanvas, string name, GTPolygon maxExtent)
            : base(mapSource, mapCanvas, name, maxExtent)
        {
            _kaMapSource = mapSource;
        }

        protected override string CreateTileReqString(double tileScale, int tlX, int tlY)
        {
            string layerStr = GetLayersString();
            string groupStr = GetGroupsString();

            string tileUriStr = "?map=" + _kaMapSource.MapName + "&s=" + tileScale.ToString()
                + "&l=" + tlX.ToString() + "&t=" + tlY.ToString() + "&g=" + groupStr + "&layers=" + layerStr;

            return tileUriStr;
        }

        protected override GTCoordinate GetGeoPointFromTileCoord(int tileX, int tileY, double tileScale)
        {
            double lon = GetTileLon(tileX, tileScale);
            double lat = GetTileLat(tileY, tileScale);

            GTCoordinate geoPoint = new GTCoordinate(lon, lat);

            return geoPoint;
        }

        protected override GTCoordinate GetTileOrigin(double lon, double lat, double tileScale)
        {
            int originX = GetTileOriginX(lon, tileScale);
            int originY = GetTileOriginY(lat, tileScale);

            GTCoordinate tileOrigin = new GTCoordinate(originX, originY);

            return tileOrigin;
        }

        int GetTileOriginX(double lon, double tileScale)
        {
            double pixelPerUnit = GetPixelPerUnit(tileScale);
            int tileXNum = (int)Math.Floor(lon * pixelPerUnit / _kaMapSource.TileWidth);
            return _kaMapSource.TileWidth * tileXNum;
        }

        int GetTileOriginY(double lat, double tileScale)
        {
            double pixelPerUnit = GetPixelPerUnit(tileScale);
            int flip = (_mapCanvas.FlipY) ? -1 : 1;
            int tileYNum = (int)Math.Floor(lat * pixelPerUnit / _kaMapSource.TileHeight) * flip;
            return _kaMapSource.TileHeight * tileYNum;
        }

        double GetTileLon(int tileX, double tileScale)
        {
            double pixelPerUnit = GetPixelPerUnit(tileScale);
            return (double)tileX / pixelPerUnit;
        }

        double GetTileLat(int tileY, double tileScale)
        {
            double pixelPerUnit = GetPixelPerUnit(tileScale);
            int flip = (_mapCanvas.FlipY) ? -1 : 1;
            return (double)tileY / pixelPerUnit * flip;
        }

        string GetLayersString()
        {
            string layerString = "";
            string splitter = "";
            foreach (string layer in _kaMapSource.Layers)
            {
                layerString += layer + splitter;
                splitter = ",";
            }
            return layerString;
        }

        string GetGroupsString()
        {
            string groupString = "";
            string splitter = "";
            foreach (string group in _kaMapSource.Groups)
            {
                groupString += group + splitter;
                splitter = ",";
            }
            return groupString;
        }

        double GetPixelPerUnit(double tileScale)
        {
            int tileDpi = _kaMapSource.Dpi;
            double inchePerUnit = AzukiMapSettings.InchesPerUnit(_kaMapSource.CoordUnit);
            double pixelPerUnit = inchePerUnit * tileDpi / tileScale;

            return pixelPerUnit;
        }

    }
}
